﻿using System;
using Gtk;
using Glade;
using System.IO;
using GerritDrost.VirtualBoxManager;
using System.Collections.Generic;

namespace GtkVirtualBoxManager
{
    public class GladeApp
    {
        public static void Main(string[] args)
        {
            new GladeApp(args);
        }

        const int NAME_COLUMN = 0;
        const int RUNNING_COLUMN = 1;
        const int UUID_COLUMN = 2;
        
        [Widget]
        Button suspendButton;
        [Widget]
        Button resumeButton;
        [Widget]
        TreeView vmTree;
        [Widget]
        Window mainWindow;

        ListStore vmStore;

        public GladeApp(string[] args)
        {
            string virtualboxPath = "";

            if (args.Length > 0)
                virtualboxPath = args[0];

            Application.Init();

            Stream xmlStream = new FileStream(Path.Combine("assets", "mainform.glade"), FileMode.Open);
            Glade.XML gxml = new Glade.XML(xmlStream, "mainWindow", null);

            gxml.Autoconnect(this);

            TreeViewColumn nameColumn = new Gtk.TreeViewColumn() { Title = "Name" };
            CellRendererText nameCellRenderer = new CellRendererText ();
            nameColumn.PackStart(nameCellRenderer, true);
            nameColumn.AddAttribute(nameCellRenderer, "text", NAME_COLUMN);

            TreeViewColumn runningColumn = new Gtk.TreeViewColumn() { Title = "Running" };
            CellRendererText runningCellRenderer = new CellRendererText();
            runningColumn.PackStart(runningCellRenderer, false);
            runningColumn.AddAttribute(runningCellRenderer, "text", RUNNING_COLUMN);

            vmTree.AppendColumn(nameColumn);
            vmTree.AppendColumn(runningColumn);

            vmStore = new ListStore(typeof(string), typeof(bool), typeof(string));
            vmTree.Model = vmStore;

            vmTree.Selection.Changed += Selection_Changed;

            suspendButton.Clicked += suspendButton_Clicked;
            resumeButton.Clicked += resumeButton_Clicked;

            manager = new VirtualMachineManager(virtualboxPath, 5000);
            updateDelegate = new VirtualMachineManager.MachinesUpdatedDelegate(updateVirtualMachines);
            manager.MachinesUpdated += updateVirtualMachines;

            mainWindow.WindowStateEvent += mainWindow_WindowStateEvent;
            mainWindow.DeleteEvent += mainWindow_DeleteEvent;
            
            Application.Run();
        }

        void resumeButton_Clicked(object sender, EventArgs e)
        {
            if (selected != null)
                manager.ResumeVirtualMachine(selected.Uuid);
        }

        void suspendButton_Clicked(object sender, EventArgs e)
        {
            if (selected != null)
                manager.SuspendVirtualMachine(selected.Uuid);
        }

        void mainWindow_DeleteEvent(object o, DeleteEventArgs args)
        {
            Application.Quit();
        }

        VirtualMachine selected;
        void Selection_Changed(object sender, EventArgs e)
        {
            updateSelection();            
        }

        void updateSelection()
        {
            TreeModel model;
            TreeIter iter;

            if (vmTree.Selection.GetSelected(out model, out iter))
            {
                string uuid = (string)model.GetValue(iter, UUID_COLUMN);
                selected = manager.GetVirtualMachine(uuid);

                resumeButton.Sensitive = !selected.Running; 
                suspendButton.Sensitive = selected.Running;
            }   
        }


        void mainWindow_WindowStateEvent(object o, WindowStateEventArgs args)
        {
            if (!manager.IsPolling && args.Event.Window.IsVisible)
                manager.StartPolling();
            else if (manager.IsPolling)
                manager.StopPolling();
        }
        VirtualMachineManager manager;
        private VirtualMachineManager.MachinesUpdatedDelegate updateDelegate;

        List<string> loadedVirtualMachines = new List<string>();

        void updateVirtualMachines()
        {

            string uuid, name;
            bool running;

            VirtualMachine machine;
            TreeIter iter;

            loadedVirtualMachines.Clear();

            if (vmStore.GetIterFirst(out iter)) {
                do
                {
                    name = (string)vmStore.GetValue(iter, NAME_COLUMN);
                    running = (bool)vmStore.GetValue(iter, RUNNING_COLUMN);
                    uuid = (string)vmStore.GetValue(iter, UUID_COLUMN);

                    machine = manager.GetVirtualMachine(uuid);

                    if (machine != null)
                    {
                        loadedVirtualMachines.Add(machine.Uuid);

                        if (name != machine.Name)
                            vmStore.SetValue(iter, NAME_COLUMN, machine.Name);

                        if (running != machine.Running)
                            vmStore.SetValue(iter, RUNNING_COLUMN, machine.Running);

                        if (uuid != machine.Uuid)
                            vmStore.SetValue(iter, UUID_COLUMN, machine.Uuid);
                    }
                    else if (!vmStore.Remove(ref iter))
                        break;
                    
                } while (vmStore.IterNext(ref iter));
            }

            foreach (VirtualMachine currentMachine in manager.VirtualMachines)
                if (!loadedVirtualMachines.Contains(currentMachine.Uuid))
                    vmStore.AppendValues(currentMachine.Name, currentMachine.Running, currentMachine.Uuid);

            updateSelection();
            
        }
    }
}
